/**
 * GenericDistribution: Defines the characteristics common to all the laws (= distribution) used
 *
 * @ Author married Ladoue
 * @ Version 0.1, 06/08/02
 */
package br.unb.statistic.distribution;

import java.util.HashMap;

import JSci.maths.statistics.NormalDistribution;
import br.unb.utils.Resource;

public abstract class GenericDistribution {

    // Variable lists
    /**
     * The name of the distribution (eg, Pareto, Weibull, ...)
     */
    public String name;
    /**
     * The number of parameters characterizing the distribution
     */
    protected int paramsCount;
    /**
     * Tables of values of different parameters
     */
    public double params[];
    /**
     * The name of parameters
     */
    public String paramNames[];

    // Definition of core values statistics: cdf, pdf ..
    /**
     * Returns the value of the pdf (x)
     */
    public abstract double pdf(double x);

    /**
     * Returns the value of the cumulative distribution function at x
     */
    public abstract double cdf(double x);

    /**
     * Returns the mean of the distribution
     */
    public abstract double mean();

    /**
     * Returns the variance of the distribution
     */
    public abstract double var();
    protected NormalDistribution normalStandard = new NormalDistribution();

    /**
     * Returns the value of the standardized normal cumulative distribution function at x
     */
    public double normalStandardCdf(double x) {
        return 0;
    }

    /**
     * Returns the value of idx-th parameter
     */
    public double getParam(int idx) {
        return params[idx];
    }

    /**
     * Sets the value of one or several parameters
     */
    public void setParam(int unParam, double uneValeur) throws IllegalArgumentException {
        if (unParam < paramsCount) {
            if (Double.compare(0, uneValeur) < 0) {
                params[unParam] = uneValeur;
            } else {
                throw new IllegalArgumentException(
                        getParamName(unParam)
                        + Resource.getString("MUST_BE_GREATER_THAN_ZERO")
                        + uneValeur);
            }
        } else {
            throw new IllegalArgumentException(
                    Resource.getString("THE_LAW")
                    + getName()
                    + Resource.getString("IS_FUNCTION_OF")
                    + paramsCount
                    + Resource.getString("PARAMETERS"));
        }
    }

    public void setParams(double[] desParams) throws IllegalArgumentException {

        if (desParams.length == getParamsCount() && hasValidParam(desParams)) {
            for (int i = 0; i < paramsCount; i++) {
                if (desParams[i] > 0) {
                    params[i] = desParams[i];
                } else {
                    throw new IllegalArgumentException(
                            Resource.getString("THE_PARAMETER")
                            + getParamName(i)
                            + Resource.getString("MUST_BE_POSITIVE"));
                }
            }
        } else {
            throw new IllegalArgumentException(
                    Resource.getString("THE_NUMBER_OF_PARAMETERS_OF_THE_LAW_OF")
                    + getName()
                    + Resource.getString("IS")
                    + paramsCount);
        }
    }

    /**
     * Returns and sets the name of the law
     */
    public String getName() {
        return name;
    }

    protected void setName(String name) {
        this.name = name;
    }

    // Make it abstract so subclasses must implement it !
    public abstract String getEquation();

    /*
     * Check that the parameters are valid for the distribution.
     */
    public abstract boolean hasValidParam(double[] desParams);

    /**
     * Returns and sets the number of parameter distribution
     */
    public int getParamsCount() {
        return paramsCount;
    }

    protected void setParamsCount(int unNbParams) {
        this.paramsCount = unNbParams;
    }

    // Methodes a probleme
    public double[] getParams() {
        return params;
    }

    protected void setParamsName(String names[]) {
        paramNames = names;
    }

    protected void setParamName(int idx, String pName) {
        paramNames[idx] = pName;
    }

    public String[] getParamsNames() {
        return paramNames;
    }

    public String getParamName(int idx) {
        return paramNames[idx];
    }

    public abstract double inverseCdf(double x);

    public abstract void setParameters(HashMap parameters);
}
